#!/usr/bin/python -u
#
# This program is copyright (c) 2009 Artur Kaszuba.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, version 2.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA  02111-1307  USA.

import os, sys, commands, re

version = "0.1"

# Define options
from optparse import OptionParser
parser = OptionParser(	usage="usage: %prog [options]",
			version="%prog: " + version,
			description="SNMP Feeder module to stat vserver")
parser.add_option("--save",
		action="store_true",
		dest="save",
		help="Save stats to stdout")
(options, args) = parser.parse_args()

# Define statistic line
cmp_line_nsproxy=re.compile(r"""^([a-zA-Z0-9-]*):\s*    # Name
		([0-9A-Za-z-]*)\s*               # cur
		""", re.VERBOSE)

cmp_line_limit=re.compile(r"""^([a-zA-Z0-9-]*):\s*    # Name
		([0-9-]*)\s*                    # cur
		([0-9-]*)/\s*([0-9-]*)\s*          # min/max
		([0-9-]*)/\s*([0-9-]*)\s*          # soft/hard
		([0-9-]*)\s*                    # hits
		""", re.VERBOSE)


def AnalyzeStatLineVSlimit(line):
	if cmp_line_limit.match(line):
		m = cmp_line_limit.match(line)
		tmp = {}
		tmp['name'] = m.group(1)
		tmp['cur'] = m.group(2)
		tmp['min'] = m.group(3)
		tmp['max'] = m.group(4)
		tmp['soft'] = m.group(5)
		tmp['hard'] = m.group(6)
		tmp['hits'] = m.group(7)
		return tmp

def AnalyzeStatLineVSnsproxy(line):
	if cmp_line_nsproxy.match(line):
		m = cmp_line_nsproxy.match(line)
		tmp = {}
		tmp['name'] = m.group(1)
		tmp['val'] = m.group(2)
		return tmp

def GetStats():
	statdir='/proc/virtual'
	if os.path.exists(statdir):
		vslist=os.listdir(statdir)
	else:
		return
	out={}
	for vsname in vslist:
		if vsname in ['status', 'info']:
			continue
		# readl limits
		statfile='%s/%s/limit' % (statdir, vsname)
		if not os.path.exists(statfile):
			continue
		out[ vsname ] = {}
		f=open(statfile, 'r')
		for line in f:
			#print line
			tmp = AnalyzeStatLineVSlimit(line)
			#print tmp
			if isinstance(tmp, dict):
				if tmp['name'] == 'VM':
					out[ vsname ][ 'vm_cur'] = int(tmp['cur']) * 4
					out[ vsname ][ 'vm_max'] = int(tmp['max']) * 4
				if tmp['name'] == 'RSS':
					out[ vsname ][ 'rss_cur'] = int(tmp['cur']) * 4
					out[ vsname ][ 'rss_max'] = int(tmp['max']) * 4
				if tmp['name'] == 'PROC':
					out[ vsname ][ 'proc_cur'] = int(tmp['cur'])
					out[ vsname ][ 'proc_max'] = int(tmp['max'])
		# read nsproxy
		statfile='%s/%s/nsproxy' % (statdir, vsname)
		if not os.path.exists(statfile):
			continue
		f=open(statfile, 'r')
		for line in f:
			#print line
			tmp = AnalyzeStatLineVSnsproxy(line)
			#print tmp
			if isinstance(tmp, dict):
				if tmp['name'] == 'NodeName':
					#print out
					out[ vsname ]['nodename'] = tmp['val']
	return out

def ReadModuleConfig(filename):
	"""Read configuration file"""
	from configobj import ConfigObj
	if os.path.exists(filename):
		conf = ConfigObj(filename)
	else:
		print "Missing config file %s" % filename
		sys.exit(1)
	return conf

config = ReadModuleConfig('/etc/snmp-feeder/modules/vservers')

# Check options
if options.save:
	stats=GetStats()
	#print stats
	for vsindex,stats in stats.items():
		print "%s %s %s %s %s %s %s %s" % (\
		vsindex,
		stats['nodename'],
		stats['vm_cur'],
		stats['vm_max'],
		stats['rss_cur'],
		stats['rss_max'],
		stats['proc_cur'],
		stats['proc_max'],
		)
